<?php

declare(strict_types=1);

namespace App\Controller;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;

#[Controller]
class GatewayController extends AbstractController
{
    #[Inject]
    protected RequestInterface $request;

    #[Inject]
    protected ResponseInterface $response;

    #[GetMapping(path: '/gateway')]
    public function index(): array
    {
        return [
            'message' => 'Hyperf Microservice Gateway',
            'version' => '1.0.0',
            'description' => 'HTTP Gateway for Microservice RPC Calls',
            'services' => [
                'notice' => 'hyperf_notice_local:9501',
                'data' => 'hyperf_data:9509',
                'nacos' => 'nacos:8848',
            ],
            'endpoints' => [
                'GET /gateway' => 'Gateway info',
                'GET /gateway/health' => 'Health check',
                'GET /gateway/api/notice/*' => 'Proxy to notice service',
                'GET /gateway/api/data/*' => 'Proxy to data service',
                'POST /gateway/api/rpc/notice/*' => 'RPC call to notice service',
                'POST /gateway/api/rpc/data/*' => 'RPC call to data service',
            ]
        ];
    }

    #[GetMapping(path: '/gateway/health')]
    public function health(): array
    {
        $services = [
            'notice' => $this->checkService('http://hyperf_notice_local:9501/'),
            'data' => $this->checkService('http://hyperf_data:9509/'),
            'nacos' => $this->checkService('http://nacos:8848/nacos/'),
        ];

        $allHealthy = !in_array(false, $services, true);

        return [
            'status' => $allHealthy ? 'healthy' : 'unhealthy',
            'services' => $services,
            'timestamp' => date('Y-m-d H:i:s'),
        ];
    }




    // 测试 Notice 服务的 RPC 调用
    #[GetMapping(path: '/gateway/api/notice/test-rpc')]
    public function testNoticeRpc(): array
    {
        try {
            $client = new \GuzzleHttp\Client(['timeout' => 10]);
            $response = $client->get('http://hyperf_notice_local:9501/test-rpc');
            $data = json_decode($response->getBody()->getContents(), true);
            
            return [
                'status' => 'success',
                'service' => 'notice',
                'method' => 'test-rpc',
                'data' => $data,
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        } catch (\Exception $e) {
            return [
                'status' => 'error',
                'service' => 'notice',
                'method' => 'test-rpc',
                'error' => $e->getMessage(),
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        }
    }

    // 测试 Notice 服务的数据库操作
    #[GetMapping(path: '/gateway/api/notice/test-db')]
    public function testNoticeDb(): array
    {
        try {
            $client = new \GuzzleHttp\Client(['timeout' => 10]);
            $response = $client->get('http://hyperf_notice_local:9501/test-db');
            $data = json_decode($response->getBody()->getContents(), true);
            
            return [
                'status' => 'success',
                'service' => 'notice',
                'method' => 'test-db',
                'data' => $data,
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        } catch (\Exception $e) {
            return [
                'status' => 'error',
                'service' => 'notice',
                'method' => 'test-db',
                'error' => $e->getMessage(),
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        }
    }

    // 测试 Notice 服务的 Redis 操作
    #[GetMapping(path: '/gateway/api/notice/test-redis')]
    public function testNoticeRedis(): array
    {
        try {
            $client = new \GuzzleHttp\Client(['timeout' => 10]);
            $response = $client->get('http://hyperf_notice_local:9501/test-redis');
            $data = json_decode($response->getBody()->getContents(), true);
            
            return [
                'status' => 'success',
                'service' => 'notice',
                'method' => 'test-redis',
                'data' => $data,
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        } catch (\Exception $e) {
            return [
                'status' => 'error',
                'service' => 'notice',
                'method' => 'test-redis',
                'error' => $e->getMessage(),
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        }
    }

    // 测试 Data 服务的 RPC 调用
    #[PostMapping(path: '/gateway/api/data/rpc')]
    public function testDataRpc(): array
    {
        try {
            $rpcRequest = [
                'jsonrpc' => '2.0',
                'method' => '/DataService/getCampuses',
                'params' => [['requestId' => 'gateway-test-' . uniqid()]],
                'id' => 1
            ];

            $client = new \GuzzleHttp\Client(['timeout' => 10]);
            $response = $client->post('http://hyperf_data:9509/', [
                'headers' => [
                    'Content-Type' => 'application/json',
                    'Json-Rpc' => '2.0',
                ],
                'body' => json_encode($rpcRequest),
            ]);
            
            $data = json_decode($response->getBody()->getContents(), true);
            
            return [
                'status' => 'success',
                'service' => 'data',
                'method' => 'rpc',
                'request' => $rpcRequest,
                'response' => $data,
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        } catch (\Exception $e) {
            return [
                'status' => 'error',
                'service' => 'data',
                'method' => 'rpc',
                'error' => $e->getMessage(),
                'timestamp' => date('Y-m-d H:i:s'),
            ];
        }
    }

    private function proxyRequest(string $url, string $method = 'GET', ?string $body = null): PsrResponseInterface
    {
        try {
            $client = new \GuzzleHttp\Client(['timeout' => 30]);
            
            $options = [
                'headers' => $this->request->getHeaders(),
            ];
            
            if ($body !== null) {
                $options['body'] = $body;
            }
            
            $response = $client->request($method, $url, $options);

            return $this->response->withBody($response->getBody())
                ->withStatus($response->getStatusCode())
                ->withHeaders($response->getHeaders());
        } catch (\Exception $e) {
            return $this->response->json([
                'error' => 'Proxy request failed',
                'message' => $e->getMessage(),
                'url' => $url,
            ])->withStatus(500);
        }
    }

    private function checkService(string $url): bool
    {
        try {
            $client = new \GuzzleHttp\Client(['timeout' => 5]);
            $response = $client->get($url);
            return $response->getStatusCode() < 500;
        } catch (\Exception $e) {
            return false;
        }
    }
}
